package com.codi.bus.core.service.util;

import com.codi.base.util.DateUtils;
import com.codi.base.util.MoneyUtils;
import com.codi.bus.constant.FundConst;
import com.codi.bus.constant.GlobalConstant;
import com.codi.bus.core.domain.Lookup;
import com.codi.bus.core.resultModel.FundNetValueResult;
import com.codi.bus.core.service.impl.QueryServiceImpl;
import com.codi.bus.core.service.model.*;
import com.codi.bus.exception.BaseException;
import com.codi.fundData.domain.SecurityProduct;
import com.codi.message.constant.ErrorConstant;
import com.google.common.base.Strings;
import org.apache.commons.collections.map.HashedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;

import static java.math.BigDecimal.ROUND_HALF_DOWN;

/**
 * Created by asus on 2018/1/25.
 */
public class AssetsQueryUtils {
    private static final Logger logger = LoggerFactory.getLogger(QueryServiceImpl.class);


    /**
     * 判断是否有在途
     *
     * @param applys
     * @param lookups
     * @param needT0
     * @param fundCode
     * @return
     */
    public static boolean checkInTransit(List<ApplyModel> applys, List<Lookup> lookups, boolean needT0, String fundCode) {
        String selectAB = selectAB(lookups, fundCode);
        // 判断是否有在途的交易
        for (ApplyModel model : applys) {
            if (needT0) {
                // 未确认并且不能是无效扣款状态
                if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                    && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_INVALID)
                    && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_UNCHECK)
                    && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY)
                    && isT0Fund(lookups, model.getFundCode())
                    && (fundCode == null || fundCode.equals(model.getFundCode()) || model.getFundCode().equals(selectAB))) {

                    return true;
                }
            } else {
                // 未确认并且不能是无效扣款状态
                if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                    && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_INVALID)
                    && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_UNCHECK)
                    && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY)
                    && !isT0Fund(lookups, model.getFundCode()) && (fundCode == null || fundCode.equals(model.getFundCode()))) {

                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 判断组合中基金是否有在途
     *
     * @param applys
     * @param lookups
     * @param fundCode
     * @return
     */
    public static boolean checkInTransitPortfolio(List<ApplyModel> applys, List<Lookup> lookups, String fundCode, String portfolioCode) {
        // 判断是否有在途的交易
        for (ApplyModel model : applys) {
            //logger.info("基金计算区  扣款状态 = {}, 业务编码 = {}, 组合编码 = {}， 基金Code = {}",model.getDeductStatus(), model.getFundBusinCode(), model.getPortfolioCode(), model.getFundCode());
            // 未确认并且不能是无效扣款状态
            if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_INVALID)
                && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_UNCHECK)
                && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY)
                && portfolioCode.equals(model.getPortfolioCode())
                && !isT0Fund(lookups, model.getFundCode()) && (fundCode == null || fundCode.equals(model.getFundCode()))) {
                //logger.info("组合有在途 fundCode = {}", model.getFundCode());
                return true;
            }
        }
        return false;
    }

    /**
     * 判断非组合基金是否有在途
     *
     * @param applys
     * @param lookups
     * @param fundCode
     * @return
     */
    public static boolean checkInTransitWithoutPortfolio(List<ApplyModel> applys, List<Lookup> lookups, String fundCode) {
        String selectAB = selectAB(lookups, fundCode);
        // 判断是否有在途的交易
        for (ApplyModel model : applys) {
            // 未确认并且不能是无效扣款状态
            if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_INVALID)
                && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_UNCHECK)
                && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY)
                && Strings.isNullOrEmpty(model.getPortfolioCode())
                && !isT0Fund(lookups, model.getFundCode()) && (fundCode == null || fundCode.equals(model.getFundCode()))) {

                return true;
            }
        }

        return false;
    }

    /**
     * 计算在途金额
     *
     * @param applys
     * @param lookups
     * @param needT0
     * @param fundCode
     * @return
     */
    public static BigDecimal sumOfInTransit(List<ApplyModel> applys, List<Lookup> lookups, boolean needT0, String fundCode) {
        BigDecimal amount = new BigDecimal(0);
        String selectAB = selectAB(lookups, fundCode);
        // 计算在途金额
        for (ApplyModel model : applys) {
            if (needT0) {
                // 未确认并且不能是无效扣款状态
                if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                    && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_UNCHECK)
                    && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_INVALID)
                    && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY)
                    && isT0Fund(lookups, model.getFundCode())
                    && (fundCode == null || fundCode.equals(model.getFundCode()) || model.getFundCode().equals(selectAB))) {

                    amount = MoneyUtils.add(amount, model.getBalance());
                }
            } else {
                // 未确认并且不能是无效扣款状态
                if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                    && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_INVALID)
                    && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_UNCHECK)
                    && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY)
                    && !isT0Fund(lookups, model.getFundCode())
                    && (fundCode == null || fundCode.equals(model.getFundCode()) || model.getFundCode().equals(selectAB))
                    && !model.getBusinAssCode().equals(GlobalConstant.BUSIN_ASS_CODE_CURRENCY_SEEL_THEN_BUY)){
                    //logger.info("业务辅助代码：{},基金编码：{}，确认信息：{}，扣款状态：{}",model.getBusinAssCode(),model.getFundCode(),model.getTAConfirmFlag(),model.getDeductStatus());
                    amount = MoneyUtils.add(amount, model.getBalance());
                }
                //logger.info("基金计算区  扣款状态 = {}, 业务编码 = {}, 组合编码 = {}， 基金Code = {}, amount = {}",model.getDeductStatus(), model.getFundBusinCode(), model.getPortfolioCode(), model.getFundCode(), amount);
            }
        }

        return amount;
    }

    /**
     * 计算组合中的基金在途金额
     *
     * @param applys
     * @param lookups
     * @param fundCode
     * @return
     */
    public static BigDecimal sumOfInTransitPortfolio(List<ApplyModel> applys, List<Lookup> lookups, String fundCode, String portfolioCode) {
        BigDecimal amount = new BigDecimal(0);
        String selectAB = selectAB(lookups, fundCode);
        // 计算在途金额
        for (ApplyModel model : applys) {
            // 未确认并且不能是无效扣款状态
            if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_UNCHECK)
                && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_INVALID)
                && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY)
                && !isT0Fund(lookups, model.getFundCode())
                && portfolioCode.equals(model.getPortfolioCode())
                && (fundCode == null || fundCode.equals(model.getFundCode()) || model.getFundCode().equals(selectAB))) {

                amount = MoneyUtils.add(amount, model.getBalance());
            }
            //logger.info("组合计算区 扣款状态 = {}, 业务编码 = {}, 组合编码 = {}， 基金Code = {}, amount = {}",model.getDeductStatus(), model.getFundBusinCode(), model.getPortfolioCode(), model.getFundCode(), amount);
        }

        return amount;
    }

    /**
     * 计算非组合中的基金在途金额
     *
     * @param applys
     * @param lookups
     * @param fundCode
     * @return
     */
    public static BigDecimal sumOfInTransitWithoutPortfolio(List<ApplyModel> applys, List<Lookup> lookups, String fundCode) {
        BigDecimal amount = new BigDecimal(0);
        String selectAB = selectAB(lookups, fundCode);
        // 计算在途金额
        for (ApplyModel model : applys) {
            // 未确认并且不能是无效扣款状态
            if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_UNCHECK)
                && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_UNCHECK)
                && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_INVALID)
                && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY)
                && !isT0Fund(lookups, model.getFundCode())
                && Strings.isNullOrEmpty(model.getPortfolioCode())
                && (fundCode == null || fundCode.equals(model.getFundCode()) || model.getFundCode().equals(selectAB))
                && !model.getBusinAssCode().equals(GlobalConstant.BUSIN_ASS_CODE_CURRENCY_SEEL_THEN_BUY)) {
                amount = MoneyUtils.add(amount, model.getBalance());
                //logger.info("基金非组合业务辅助代码：{},基金编码：{}，确认信息：{}，扣款状态：{}",model.getBusinAssCode(),model.getFundCode(),model.getTAConfirmFlag(),model.getDeductStatus());
            }
        }

        return amount;
    }

    private static String selectAB(List<Lookup> lookups, String fundCode) {
        Lookup hit = null;
        Map<String, String> temp = new HashedMap();

        for (Lookup lu : lookups) {
            if (lu.getRuleValue().equals(fundCode)) {
                hit = lu;
            }
            temp.put(lu.getRuleText(), lu.getRuleValue());
        }
        if (hit != null) {
            if (hit.getRuleText().contains("A")) {
                return temp.get(hit.getRuleText().replace("A", "B"));
            } else if (hit.getRuleText().contains("B")) {
                return temp.get(hit.getRuleText().replace("B", "A"));
            }
        }
        return null;
    }

    private static Integer numOfInTransit(List<ApplyModel> applys, List<Lookup> lookups, boolean needT0, String fundCode) {
        Integer amount = new Integer(0);
        String selectAB = selectAB(lookups, fundCode);
        // 计算在途金额
        for (ApplyModel model : applys) {
            if (needT0) {
                // 未确认并且不能是无效扣款状态
                if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                    && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_UNCHECK)
                    && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_INVALID)
                    && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY)
                    && isT0Fund(lookups, model.getFundCode())
                    && (fundCode == null || fundCode.equals(model.getFundCode()) || model.getFundCode().equals(selectAB))) {

                    amount++;
                }
            } else {
                // 未确认并且不能是无效扣款状态
                if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                    && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_UNCHECK)
                    && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_INVALID)
                    && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY)
                    && !isT0Fund(lookups, model.getFundCode())
                    && Strings.isNullOrEmpty(model.getPortfolioCode())
                    && (fundCode == null || fundCode.equals(model.getFundCode()) || model.getFundCode().equals(selectAB))) {

                    amount++;
                }
            }
        }

        return amount;
    }

    /**
     * 非组合基金赎回在途笔数
     * @param applys
     * @param lookups
     * @param needT0
     * @param fundCode
     * @return
     */
    public static Integer numSellOfInTransit(List<ApplyModel> applys, List<Lookup> lookups, boolean needT0, String fundCode) {
        Integer amount = new Integer(0);
        String selectAB = selectAB(lookups, fundCode);
        // 计算在途金额
        for (ApplyModel model : applys) {
            if (needT0) {
                // 未确认并且不能是无效扣款状态
                if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                    && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_SELL)
                    && isT0Fund(lookups, model.getFundCode())
                    && (fundCode == null || fundCode.equals(model.getFundCode()) || model.getFundCode().equals(selectAB))) {

                    amount++;
                }
            } else {
                // 未确认并且不能是无效扣款状态
                if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                    && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_SELL)
                    && !isT0Fund(lookups, model.getFundCode())
                    && Strings.isNullOrEmpty(model.getPortfolioCode())
                    && (fundCode == null || fundCode.equals(model.getFundCode()) || model.getFundCode().equals(selectAB))) {

                    amount++;
                }
            }
        }
        return amount;
    }

    /**
     * 计算组合中的基金在途笔数
     *
     * @param applys
     * @param lookups
     * @param fundCode
     * @return
     */
    private static Integer numOfInTransitPortfolio(List<ApplyModel> applys, List<Lookup> lookups, String fundCode, String portfolioCode) {
        Integer amount = new Integer(0);
        String selectAB = selectAB(lookups, fundCode);
        List<String> orderTime = new ArrayList<>();
        // 计算在途金额
        for (ApplyModel model : applys) {
            // 未确认并且不能是无效扣款状态
            if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_UNCHECK)
                && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_INVALID)
                && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY)
                && !isT0Fund(lookups, model.getFundCode())
                && portfolioCode.equals(model.getPortfolioCode())
                && (fundCode == null || fundCode.equals(model.getFundCode()) || model.getFundCode().equals(selectAB))) {
                if (orderTime.size() != 0) {
                    for (String p : orderTime) {
                        if (model.getOrderTime().equals(p)) {
                            amount--;
                            break;
                        }
                    }
                }
                amount++;
                orderTime.add(model.getOrderTime());
            }
        }

        return amount;
    }

    /**
     * 计算组合中赎回的基金在途笔数
     *
     * @param applys
     * @param lookups
     * @param fundCode
     * @return
     */
    public static Integer numOfSellInTransitPortfolio(List<ApplyModel> applys, List<Lookup> lookups, String fundCode, String portfolioCode) {
        Integer amount = new Integer(0);
        String selectAB = selectAB(lookups, fundCode);
        List<String> orderTime = new ArrayList<>();
        // 计算在途金额
        for (ApplyModel model : applys) {
            // 未确认并且不能是无效扣款状态
            if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_SELL)
                && !isT0Fund(lookups, model.getFundCode())
                && portfolioCode.equals(model.getPortfolioCode())
                && (fundCode == null || fundCode.equals(model.getFundCode()) || model.getFundCode().equals(selectAB))) {
                if (orderTime.size() != 0) {
                    for (String p : orderTime) {
                        if (model.getOrderTime().equals(p)) {
                            amount--;
                            break;
                        }
                    }
                }
                amount++;
                orderTime.add(model.getOrderTime());
            }
        }
        return amount;
    }

    /**
     * 计算非组合中的基金在途笔数
     *
     * @param applys
     * @param lookups
     * @param fundCode
     * @return
     */
    public static Integer numOfInTransitWithoutPortfolio(List<ApplyModel> applys, List<Lookup> lookups, String fundCode) {
        Integer amount = new Integer(0);
        String selectAB = selectAB(lookups, fundCode);
        // 计算在途金额
        for (ApplyModel model : applys) {
            // 未确认并且不能是无效扣款状态
            if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_UNCONFIRM)
                && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_UNCHECK)
                && !model.getDeductStatus().equals(GlobalConstant.DEDUCT_STATUS_INVALID)
                && model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_APPLY_BUY)
                && !isT0Fund(lookups, model.getFundCode())
                && Strings.isNullOrEmpty(model.getPortfolioCode())
                && (fundCode == null || fundCode.equals(model.getFundCode()) || model.getFundCode().equals(selectAB))) {
                amount++;
            }
        }

        return amount;
    }

    /**
     * 判断是否是T0基金
     *
     * @param lookups
     * @param fundCode
     * @return
     */
    public static boolean isT0Fund(List<Lookup> lookups, String fundCode) {
        if (CollectionUtils.isEmpty(lookups)) {
            return false;
        }
        for (Lookup lookup : lookups) {
            if (lookup.getRuleValue().equals(fundCode)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 计算 总资产，总当日收益，最新净值日期，是否有在途
     *
     * @param funds
     * @param needT0
     * @param fastRedeemShares
     * @return
     */
    public static AssetFundModel sumOfAsset(List<AssetFundModel> funds, boolean needT0, Map<String, BigDecimal> fastRedeemShares, Map<String, BigDecimal> lastNetValues,
                                            Map<String, BigDecimal> todayFastRedeemShares,
                                             List<ShareDetailQryModel> shareDetailQryModels, List<DividendModel> dividendModels,List<IncomeModel> incomeModels
                                            , Map<String, BigDecimal> map) {
        // 同个基金的汇总
        Map<String, AssetFundModel> fundSums = new HashMap<>();
        // 最新的净值日期
        Date lastNetDate = null;
        // 基金代码
        String fundCode = null;
        // 计算总和
        for (AssetFundModel model : funds) {
            // 是否是T0基金
            boolean isT0 = model.getAssetType() == GlobalConstant.ASSET_TYPE_WALLET;
            if (needT0 && !isT0) {
                continue;
            }

            if (!needT0 && isT0) {
                continue;
            }

            // 基金代码
            fundCode = model.getFundCode();
            // 每个fundCode, 一个AssetFundModel
            if (!fundSums.containsKey(fundCode)) {
                fundSums.put(fundCode, model);
            } else {
                AssetFundModel innerFund = fundSums.get(fundCode);
                // 累加未付收益 - add by Shangdu Lin - 20170612
                innerFund.setUnpaidIncome(MoneyUtils.add(innerFund.getUnpaidIncome(), model.getUnpaidIncome()));
                // 累加当前份额
                innerFund.setCurrentShares(MoneyUtils.add(innerFund.getCurrentShares(), model.getCurrentShares()));
            }

            // 设置最新净值日期
            Date netDate = model.getNetValueDate();
            if (lastNetDate == null) {
                lastNetDate = netDate;
            } else {
                // 如果比当前净值日期大，则用大的
                if (lastNetDate.before(netDate)) {
                    lastNetDate = netDate;
                }
            }
        }

//        /**
//         * Shangdu Lin - 20170419
//         * 非货币基金、货币基金：如果净值日期小于当前工作日，则应确认日期是当前工作日的基金份额
//         */
//        if (!CollectionUtils.isEmpty(confirms)) {
//            for (Map.Entry<String, AssetFundModel> entry : fundSums.entrySet()) {
//                AssetFundModel model = entry.getValue();
//                if (dateBefore(model.getNetValueDate(), currentWorkingDate)) {
//                    BigDecimal confirmedShares = getConfirmShares(confirms, model.getFundCode(), currentWorkingDate);
//                    model.setCurrentSharesWithoutTodayConfirmed(MoneyUtils.subtract(model.getCurrentShares(), confirmedShares));
//                }
//            }
//        }

        // 如果是T0, 先减掉快速赎回的份额
        // 计算总资产值和总日收益
        BigDecimal totalWorthValue = null;
        BigDecimal totalTodayIncome = null;
        BigDecimal totalShareIncome = null;
        BigDecimal totalAccumIncome = null;
        //累计收益 - add by Shangdu Lin - 20170531
        //BigDecimal totalAccumIncome=null;
        // 未付收益 - add by Shangdu Lin - 20170612
        BigDecimal totalUnpaidIncome = null;
        //持有基金列表
        List<AssetFundModel> fundDetailList = new ArrayList<AssetFundModel>();
        for (Map.Entry<String, AssetFundModel> entry : fundSums.entrySet()) {
            AssetFundModel model = entry.getValue();

            BigDecimal currentShares = model.getCurrentShares();
//            BigDecimal currentSharesWithoutLastT0 = model.getCurrentSharesWithoutTodayConfirmed();
            BigDecimal enableShares = model.getEnableShares();
            // 如果当前工作日没有待确认的份额，则使用当前份额
//            if (currentSharesWithoutLastT0 == null) {
//                currentSharesWithoutLastT0 = model.getCurrentShares();
//            }
            // 当前份额减掉快速赎回的份额
            if (needT0 && fastRedeemShares.containsKey(entry.getKey())) {
                currentShares = MoneyUtils.subtract(currentShares, fastRedeemShares.get(entry.getKey()));
            }

//            // 当前份额减掉当前净值日期的快速赎回的份额，当前净值日期为上一工作日， 因为上一工作日的快速赎回的份额不会有日收益
//            if (needT0 && lastFastRedeemShares.containsKey(entry.getKey())) {
//                currentSharesWithoutLastT0 = MoneyUtils.subtract(currentSharesWithoutLastT0,
//                    lastFastRedeemShares.get(entry.getKey()));
//            }

            // Shangdu Lin - 20170502
            // 4舍5入后再相加
            // why:因为在我的资产页，各个基金是分开显示的，而且每个基金都会显示资产，每个资产是4舍5入的，且基于此就算出总资产并显示
            // 资产=份额*净值
            BigDecimal worthValue = currentShares.multiply(model.getNetValue());
            //货币基金需要加上 未付收益
            worthValue = MoneyUtils.add(worthValue, model.getUnpaidIncome());
            worthValue = worthValue.setScale(2, BigDecimal.ROUND_HALF_UP);
            //设置每个基金的资产
            model.setTotalWorthValue(worthValue);
            totalWorthValue = MoneyUtils.add(totalWorthValue, worthValue);
            //logger.debug("1基金：{}，资产：{}，未付收益：{}",model.getFundCode(),worthValue,model.getUnpaidIncome());
            //计算持仓收益的现金分红部分
            /**
             *
             * 这里的分红收益总额
             *
             */
            BigDecimal totalDividend = new BigDecimal(0);
            for(DividendModel dividendModel : dividendModels){
                if ("1".equals(dividendModel.getAutoBuy()) && model.getFundCode().equals(dividendModel.getFundCode())&& dividendModel.getTradeAccount().equals(model.getTradeAcco())){
                    if (dividendModel.getDividendDate().compareTo(DateUtils.formatDate4(new Date())) < 0){
                        totalDividend = MoneyUtils.add(totalDividend,dividendModel.getDividendBalance());
                    }
                    if (DateUtils.formatDate4(new Date()).compareTo(dividendModel.getEquityRegDate()) >= 0 && DateUtils.formatDate4(new Date()).compareTo(dividendModel.getDividendDate()) <= 0){
                        model.setDividends("该基金最近有分红配送");
                    }
                }
            }
            if (model.getDividends() == null) {
                model.setDividends("");
            }
            //累计收益
            if (incomeModels.size() != 0) {
                for (IncomeModel incomeModel : incomeModels){
                    if (incomeModel.getFundCode().equals(model.getFundCode())&& incomeModel.getTradeAccount().equals(model.getTradeAcco())){
                        model.setTotalAccumIncome(MoneyUtils.add(incomeModel.getAccumIncome(),totalDividend));
                        break;
                    }
                }
            }
            totalAccumIncome = MoneyUtils.add(totalAccumIncome,model.getTotalAccumIncome());

            //持仓收益
//            BigDecimal shareIncome = MoneyUtils.add(MoneyUtils.subtract(worthValue,model.getCost()),totalDividend);
//            model.setShareIncome(shareIncome);
//            totalShareIncome = MoneyUtils.add(totalShareIncome,shareIncome);


            model.setCurrentShares(currentShares);
            model.setEnableShares(enableShares);
            //累计收益, 只有货币基金的累计收益有值，非货币基金的累计收益接口不会返回 - add by Shangdu Lin - 20170531
            // 未付收益 - add by Shangdu Lin - 20170612
            totalUnpaidIncome = MoneyUtils.add(totalUnpaidIncome, model.getUnpaidIncome());
            BigDecimal oldShares = currentShares;
            for (ShareDetailQryModel shareDetailQryModel : shareDetailQryModels){

                if (model.getFundCode().equals(shareDetailQryModel.getFundCode()) && shareDetailQryModel.getAffirmDate().equals(DateUtils.formatDate4(new Date()))){
                    oldShares = oldShares.subtract(shareDetailQryModel.getEnableShares());
                }
            }
            //今天快速赎回的份额  昨日还是有收益
            if (needT0 && todayFastRedeemShares.containsKey(entry.getKey())){
                oldShares = MoneyUtils.add(oldShares,todayFastRedeemShares.get(entry.getKey()));
                logger.debug("基金：{}，快速赎回份额：{}",entry.getKey(),todayFastRedeemShares.get(entry.getKey()));
            }


            BigDecimal todayIncome = setTodayIncome(model, oldShares, lastNetValues);
            /**
             * 昨日收益加上分红
             */
            for(DividendModel dividendModel : dividendModels){
                if ("1".equals(dividendModel.getAutoBuy()) && model.getFundCode().equals(dividendModel.getFundCode())&& dividendModel.getTradeAccount().equals(model.getTradeAcco())){
                    if (dividendModel.getDividendDate().equals(DateUtils.formatDate4(DateUtils.addDay(new Date(),-1)))){
                        todayIncome = MoneyUtils.add(todayIncome,dividendModel.getDividendBalance());
                    }
                }
            }
            // 4舍5入后再相加
            // why:因为在我的资产页，各个基金是分开显示的，而且每个基金都会显示当日收益，每个当日收益是4舍5入的，且基于此就算出总收益并显示
            // 所以这里算法需保持一致才能显示一致
            todayIncome = todayIncome.setScale(2, BigDecimal.ROUND_HALF_UP);
            //logger.debug("当日收益：{}",todayIncome);
            //设置每个基金的每日收益
            model.setTotalTodayIncome(todayIncome);
            if (needT0 && DateUtils.formatDate4(model.getNetValueDate()).equals(DateUtils.formatDate4(DateUtils.addDay(new Date(),-1)))){
                model.setTotalTodayIncomeRecord(todayIncome);
            }
            //logger.debug("昨日收益：{}",todayIncome);
            totalTodayIncome = MoneyUtils.add(totalTodayIncome, todayIncome);
            //是否在途
            //model.setInTransit(checkInTransit(applys, lookups, needT0, fundCode));
            //在途金额
            //BigDecimal oneInTransit = sumOfInTransit(applys, lookups, needT0, model.getFundCode());
            //model.setInTransitAmount(oneInTransit);
            //在途笔数
            //model.setInTransitNum(numOfInTransit(applys, lookups, needT0, model.getFundCode()));
            //设置每个基金的资产
            //model.setTotalWorthValue(MoneyUtils.add(worthValue, oneInTransit));
            //赎回在途笔数
            //Integer sellInTransit = numSellOfInTransit(applys, lookups, needT0, model.getFundCode());
            //model.setSellInTransit(sellInTransit);
            switch (model.getFundCode()){
                case GlobalConstant.T0_FUND_JINYING_A :
                    model.setWalletString("每月15日结转当期收益");
                    break;
                case GlobalConstant.T0_FUND_JINYING_B :
                    model.setWalletString("每月15日结转当期收益");
                    break;
                case GlobalConstant.T0_FUND_CHANGCHENG_A :
                    model.setWalletString("每月15日结转当期收益");
                    break;
                case GlobalConstant.T0_FUND_CHANGCHENG_B :
                    model.setWalletString("每月15日结转当期收益");
                    break;
                case GlobalConstant.T0_FUND_BAOYING_A :
                    model.setWalletString("每月5日结转当期收益");
                    break;
                case GlobalConstant.T0_FUND_BAOYING_B :
                    model.setWalletString("每月5日结转当期收益");
                    break;
                case GlobalConstant.T0_FUND_JINYING2_A :
                    model.setWalletString("每日结转当期收益");
                    break;
                case GlobalConstant.T0_FUND_JINYING2_B :
                    model.setWalletString("每日结转当期收益");
                    break;
                default:
                    break;
            }
            //logger.debug("银行编号2：{}，银行名称2：{}",model.getBankCode(),model.getBankName());
            //累加 T0基金 分红总和
            if (needT0){
                BigDecimal sumDividend = new BigDecimal(0);
                for (DividendModel dividendModel : dividendModels){
                    if (dividendModel.getFundCode().equals(model.getFundCode())){
                        sumDividend = MoneyUtils.add(sumDividend,dividendModel.getTotalDividendBalance());
                    }
                }
                map.put(model.getFundCode(),sumDividend);
            }
            //logger.warn("单个基金在途金额:{},单个基金资产:{}", model.getInTransitAmount(), model.getTotalWorthValue());
            fundDetailList.add(model);
        }

        //加上全赎的累计收益
        for (IncomeModel incomeModel : incomeModels){
            if (!fundSums.entrySet().contains(incomeModel.getFundCode())){
                totalAccumIncome = MoneyUtils.add(totalAccumIncome, incomeModel.getAccumIncome());
            }
        }

        // 基金
        AssetFundModel fund = new AssetFundModel();
        //设置基金详情
        fund.setFundModelList(fundDetailList);
        // 设置总收益
        fund.setTotalTodayIncome(totalTodayIncome);
        //设置累计收益
        fund.setTotalAccumIncome(totalAccumIncome);
        // 设置最新净值日期
        fund.setNetValueDate(lastNetDate);
        // 设置资产类别
        int assetType = GlobalConstant.ASSET_TYPE_FUND;
        if (needT0) {
            assetType = GlobalConstant.ASSET_TYPE_WALLET;
            // 这个主要是给零钱包界面使用，零钱包页面需要显示该用户当前持有的T0基金的七日年化，目前当前T0基金只有一只，213009或213909
            fund.setFundCode(fundCode);
        }
        fund.setAssetType(assetType);
        //累计收益, 只有货币基金的累计收益有值，非货币基金的累计收益接口不会返回 - add by Shangdu Lin - 20170531
        //fund.setTotalAccumIncome(totalAccumIncome);
        // 未付收益 - add by Shangdu Lin - 20170612
        fund.setTotalUnpaidIncome(totalUnpaidIncome);
        //持仓收益
        fund.setShareIncome(totalShareIncome);

        // 总基金个数
        fund.setFundsCount(fundSums.size());
//        if (havePortfolio) {
//            boolean inTransit = checkInTransit(applys, lookups, needT0, null);
//            fund.setInTransit(inTransit);
//            // 在途金额
//
//            fund.setInTransitAmount(sumOfInTransit(applys, lookups, needT0, null));
//            //在途笔数
//            fund.setInTransitNum(numOfInTransit(applys, lookups, needT0, null));
//        } else {
//            // 是否在途
//            boolean inTransit = checkInTransitWithoutPortfolio(applys, lookups, null);
//            fund.setInTransit(inTransit);
//            // 在途金额
//
//            fund.setInTransitAmount(sumOfInTransitWithoutPortfolio(applys, lookups, null));
//            //在途笔数
//            fund.setInTransitNum(numOfInTransitWithoutPortfolio(applys, lookups, null));
//        }

        // 设置总资产(确认资产+在途资产)
        fund.setTotalWorthValue(totalWorthValue);
        logger.debug("总资产2：{}",totalWorthValue);

        //logger.warn("零钱包总在途金额:{},零钱包总资产:{}", fund.getInTransitAmount(), fund.getTotalWorthValue());
        return fund;
    }

    /**
     * 获取确认成功的份额
     *
     * @param confirms
     * @param fundCode
     * @return
     */
    public static BigDecimal getConfirmShares(Collection<ConfirmModel> confirms, String fundCode, Date
        currentWorkingDate) {
        BigDecimal shares = new BigDecimal(0);
        if (CollectionUtils.isEmpty(confirms)) {
            return shares;
        }
        for (ConfirmModel model :
            confirms) {
            // 申购和定投成功的份额
            if (model.getFundCode().equals(fundCode)
                && model.getAffirmDate().equals(DateUtils.formatDate4(currentWorkingDate))
                && (model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_CONFIRM_BUY) || model.getFundBusinCode().equals(GlobalConstant.FUND_BUSIN_CODE_CONFIRM_FIX_BUY))
                && checkConfirmSuccess(model.getTAConfirmFlag())) {
                shares = MoneyUtils.add(shares, model.getConfirmShares());
            }
        }

        logger.warn("当前日期:{},基金代码:{},确认成功的份额:{}", DateUtils.formatDate4(currentWorkingDate), fundCode, shares);

        return shares;
    }

    /**
     * 判断是否确认成功
     * 1-确认成功
     * 2-部分确认
     * 3-实时确认成功
     *
     * @param confirmFlag
     * @return
     */
    public static boolean checkConfirmSuccess(String confirmFlag) {
        if (confirmFlag.equals(GlobalConstant.TACONFIRM_FLAG_CONFIRMED) || confirmFlag.equals(GlobalConstant
            .TACONFIRM_FLAG_PART_CONFIRMED) || confirmFlag.equals(GlobalConstant.TACONFIRM_FLAG_REAL_SUCCESS)) {
            return true;
        }

        return false;
    }

    /**
     * 计算 组合的在途信息
     */
    public static AssetPortfolioModel extractInTransit(List<Lookup> lookups, List<ApplyModel> applys, List<String> portfolioCode) {
        BigDecimal totalOneInTransit = new BigDecimal(0);
        int totalInTransitNum = 0;
        Boolean totalInTransit = false;
        AssetPortfolioModel assetPortfolioModel = new AssetPortfolioModel();
        for (String code : portfolioCode) {
            //是否在途
            boolean inTransit = checkInTransitPortfolio(applys, lookups, null, code);
            if (inTransit) {
                totalInTransit = true;
                //logger.info("组合有在途 code = {}" ,code);
            } else {
                //logger.info("组合没在途 code = {}" ,code);
                continue;
            }
            //在途金额
            BigDecimal oneInTransit = sumOfInTransitPortfolio(applys, lookups, null, code);
            logger.info("extractInTransit在途金额 ={}",oneInTransit);
            totalOneInTransit = MoneyUtils.add(totalOneInTransit, oneInTransit);
            //在途笔数
            int inTransitNum = numOfInTransitPortfolio(applys, lookups, null, code);
            totalInTransitNum = totalInTransitNum + inTransitNum;
        }
        assetPortfolioModel.setInTransit(totalInTransit);
        assetPortfolioModel.setInTransitNum(totalInTransitNum);
        assetPortfolioModel.setInTransitAmount(totalOneInTransit);
        return assetPortfolioModel;
    }

    /**
     * 设置聚源信息
     */
    public static FundNetValueResult setNetValue(String fundCode, FundNetValueResult netValueResult, List<FundNetValueResult> fundNetValueList) {
        Map<String, FundNetValueResult> map = new HashMap<>();
        if (map.containsKey(fundCode)) {
            netValueResult = map.get(fundCode);
        } else {
            netValueResult = getNetValue(fundNetValueList, fundCode);
            if (netValueResult == null) {
                throw new BaseException(ErrorConstant.ERROR_GILDATA_EMPTY);
            }
            map.put(fundCode, netValueResult);
        }
        return netValueResult;
    }

    /**
     * 判断是否为货币基金 为货币基金计算万份收益
     */
    public static void setIncome(FundNetValueResult netValueResult, String fundCode, AssetFundModel assetFundModel, List<Lookup> lookups) {
        // 货币基金
        if (netValueResult.getFundTypeCode().intValue() == FundConst.FUND_TYPE_CODE_CURRENCY) {
            // 此fund为货币基金
            assetFundModel.setIsCurrency(true);

            // 资产类型
            if (isT0Fund(lookups, fundCode)) {
                assetFundModel.setAssetType(GlobalConstant.ASSET_TYPE_WALLET);
            }

            // 从聚源获取万份收益
            BigDecimal dailyProfit = netValueResult.getDailyProfit();
            if (dailyProfit == null) {
                dailyProfit = new BigDecimal(0);
                logger.error("queryAssets-getDailyProfit is null for fund code ={}", fundCode);
            }
            // 万份收益
            assetFundModel.setDailyProfit(dailyProfit);

        } else {

            // 此fund为非货币基金
            assetFundModel.setIsCurrency(false);

            // 从聚源获取日收益率
            BigDecimal todayIncomeRate = netValueResult.getNvDailyGrowthRate();
            if (todayIncomeRate == null) {
                todayIncomeRate = new BigDecimal(0);
                logger.error("queryAssets-getNvDailyGrowthRate is null for fund code ={}", fundCode);
            }

            // 日收益率
            assetFundModel.setTodayIncomeRate(todayIncomeRate);
        }

    }

    /**
     * 计算当日收益
     */
    public static BigDecimal setTodayIncome(AssetFundModel assetFundModel, BigDecimal currentShare, Map<String, BigDecimal> lastNetValues) {
        BigDecimal todayIncome = null;
        if (assetFundModel.getIsCurrency()) {
            // 万份收益
            todayIncome = currentShare.divide(new BigDecimal(10000), 4)
                .multiply(assetFundModel.getDailyProfit());
            //logger.info("基金代码：{}，份额：{}，万份收益：{}",assetFundModel.getFundCode(),assetFundModel.getCurrentShares(),assetFundModel.getDailyProfit());
        } else {
            // 日收益=当前基金份额*（当天净值- 前一个工作日净值）
            BigDecimal lastUnitValue = lastNetValues.get(assetFundModel.getFundCode());
            BigDecimal margin = MoneyUtils.subtract(assetFundModel.getNetValue(), lastUnitValue);
            todayIncome = currentShare.multiply(margin);

            //logger.warn("sumOfAsset - 基金代码:{},上一工作日净值:{},当前净值:{},当前份额:{},净值差额:{},日收益:{}", assetFundModel.getFundCode(),
            //lastUnitValue, assetFundModel.getNetValue(), currentShare, margin, todayIncome);
        }
        return todayIncome;
    }

    /**
     * 按交易账号将份额和资产进行区分
     */
    public static PortfolioModel extractPortfolioByTrade(Map<String, List<CombSharesQryModel>> combTradeMap, List<Lookup> lookups,
                                                         PortfolioModel portfolioModel, List<FundNetValueResult> fundNetValueList) {
        List<PortfolioTradeModel> portfolioTrades = new ArrayList<>();
        for (String key : combTradeMap.keySet()) {
            List<AssetFundModel> portfolioFunds = new ArrayList<>();
            if (combTradeMap.get(key).get(0).getPortfolioCode().equals(portfolioModel.getPortfolioCode())) {
                BigDecimal enableShare = null;
                BigDecimal currentShare = null;
                BigDecimal totalWorthValue = null;
                BigDecimal totalTodayIncome = null;
                PortfolioTradeModel portfolioTradeModel = new PortfolioTradeModel();
                for (CombSharesQryModel combSharesQryModel : combTradeMap.get(key)) {
                    FundNetValueResult netValueResult = null;
                    netValueResult = setNetValue(combSharesQryModel.getFundCode(), netValueResult, fundNetValueList);

                    currentShare = combSharesQryModel.getFundShare();
                    enableShare = combSharesQryModel.getEnableShares();
                    BigDecimal worthValue = currentShare.multiply(netValueResult.getUnitNV());
                    worthValue = worthValue.setScale(2, BigDecimal.ROUND_HALF_UP);
                    totalWorthValue = MoneyUtils.add(totalWorthValue, worthValue);



                    AssetFundModel assetFundModel = new AssetFundModel();
                    assetFundModel.setTradeAcco(combSharesQryModel.getTradeAcco());
                    //基金代码
                    assetFundModel.setFundCode(combSharesQryModel.getFundCode());
                    //基金份额
                    assetFundModel.setCurrentShares(combSharesQryModel.getFundShare());
                    // 单位净值
                    assetFundModel.setNetValue(netValueResult.getUnitNV());
                    //可用份额
                    assetFundModel.setEnableShares(combSharesQryModel.getEnableShares());
                    //基金名称
                    assetFundModel.setFundName(netValueResult.getChiNameAbbr());
                    // 单位净值日期
                    assetFundModel.setNetValueDate(netValueResult.getTradingDay());
                    // 资产类型
                    assetFundModel.setAssetType(GlobalConstant.ASSET_TYPE_FUND);

                    //区分货币基金的收益
                    setIncome(netValueResult, combSharesQryModel.getFundCode(), assetFundModel, lookups);

                    //设置每个基金的资产
                    assetFundModel.setTotalWorthValue(worthValue);
                    portfolioFunds.add(assetFundModel);
                }
                portfolioTradeModel.setCurrentShare(currentShare);
                portfolioTradeModel.setEnableShare(enableShare);
                portfolioTradeModel.setTotalWorthValue(totalWorthValue);
                //portfolioTradeModel.setTotalTodayIncome(totalTodayIncome);
                portfolioTradeModel.setTradeAcco(key);
                portfolioTradeModel.setPortfolioFunds(portfolioFunds);
                portfolioTradeModel.setPortfolioCode(portfolioModel.getPortfolioCode());
                portfolioTrades.add(portfolioTradeModel);
            }
        }
        portfolioModel.setPortfolioTrades(portfolioTrades);
        return portfolioModel;
    }

    /**
     * 计算组合的信息
     * 传进来的是同一个组合的基金份额的列表信息
     * 得到一个组合的model
     */
    public static PortfolioModel extractPortfolio(String portfolio, List<Lookup> lookups, List<CombSharesQryModel> combSharesQryModels, List<FundNetValueResult> fundNetValueList,
                                                  Map<String, BigDecimal> lastNetValues, Map<String, List<PortfolioQryModel>> portfolioMap,
                                                  List<ShareDetailQryModel> shareDetailQryModels,
                                                  CombIncomeQryModel combIncomeQryModel, Map<String, List<DividendModel>> dividendMap,
                                                  Map<String, List<IncomeModel>> mapIncome) {
        PortfolioModel portfolioModel = new PortfolioModel();
        Map<String, FundNetValueResult> map = new HashMap<>();
        List<AssetFundModel> portfolioFunds = new ArrayList<>();
        BigDecimal portfolioWorthValue = null;
        BigDecimal portfolioTodayIncome = null;
        BigDecimal portfolioDividend = new BigDecimal(0);

        Date netValueDate = DateUtils.addDay(new Date(), -1); //默认净值日期为前一天
//        boolean                         portfolioInTransit    = false;
//        int                             portfolioInTransitNum = 0;
//        BigDecimal                      portfolioInTransitSum = new BigDecimal(0);
        for (CombSharesQryModel combSharesQryModel : combSharesQryModels) {
            FundNetValueResult netValueResult = null;
            BigDecimal currentShare = combSharesQryModel.getFundShare();
            BigDecimal enableShare = combSharesQryModel.getEnableShares();
            if (MoneyUtils.compareTo(currentShare, 0) == 0) {
                continue;
            }
            String portfolioCode = combSharesQryModel.getPortfolioCode();
            String fundCode = combSharesQryModel.getFundCode();

            AssetFundModel assetFundModel = new AssetFundModel();
            netValueResult = setNetValue(fundCode, netValueResult, fundNetValueList);
            assetFundModel.setTradeAcco(combSharesQryModel.getTradeAcco());
            //基金代码
            assetFundModel.setFundCode(combSharesQryModel.getFundCode());
            //基金份额
            assetFundModel.setCurrentShares(currentShare);
            // 单位净值
            assetFundModel.setNetValue(netValueResult.getUnitNV());
            //可用份额
            assetFundModel.setEnableShares(enableShare);
            //基金名称
            assetFundModel.setFundName(netValueResult.getChiNameAbbr());
            // 单位净值日期
            assetFundModel.setNetValueDate(netValueResult.getTradingDay());
            //获取实际的净值日期
            netValueDate = netValueResult.getTradingDay();
            // 资产类型
            assetFundModel.setAssetType(GlobalConstant.ASSET_TYPE_FUND);


            //区分货币基金的收益
            setIncome(netValueResult, fundCode, assetFundModel, lookups);
            //计算当日收益
            BigDecimal oldShares = currentShare;
            for (ShareDetailQryModel shareDetailQryModel : shareDetailQryModels){
                //logger.info("=== 基金编码：{}，确认日期：{}，可用份额：{}，交易账号：{}",shareDetailQryModel.getFundCode(),shareDetailQryModel.getAffirmDate(),shareDetailQryModel.getEnableShares(),shareDetailQryModel.getTradeAccount());
                //logger.debug("确认日期：{}，今日日期：{}，今日日期format",shareDetailQryModel.getAffirmDate(),new Date(),DateUtils.formatDate4(new Date()));
                if (combSharesQryModel.getFundCode().equals(shareDetailQryModel.getFundCode())&& shareDetailQryModel.getAffirmDate().equals(DateUtils.formatDate4(new Date())) && combSharesQryModel.getTradeAcco().equals(shareDetailQryModel.getTradeAccount())){
                    oldShares = oldShares.subtract(shareDetailQryModel.getEnableShares());
                }
            }
            //logger.info("oldShares:{},fundCode:{}",oldShares,combSharesQryModel.getFundCode());
            BigDecimal todayIncome = setTodayIncome(assetFundModel, oldShares, lastNetValues);
            //计算昨日收益的现金分红部分
            /**
             * 日收益加上分红   如果当日有分红的话
             */
            List<DividendModel> dividends = dividendMap.get(combSharesQryModel.getTradeAcco());
            for(DividendModel dividendModel : dividends){
                if ("1".equals(dividendModel.getAutoBuy())){
                    if (combSharesQryModel.getFundCode().equals(dividendModel.getFundCode()) && dividendModel.getDividendDate().equals(DateUtils.formatDate4(DateUtils.addDay(new Date(),-1)))){
                        todayIncome = MoneyUtils.add(todayIncome,dividendModel.getDividendBalance());
                    }
                }
            }

            //总的现金分红   用于累计收益
            BigDecimal totalDividend = new BigDecimal(0);
            for(DividendModel dividendModel : dividends){
                if ("1".equals(dividendModel.getAutoBuy()) && assetFundModel.getFundCode().equals(dividendModel.getFundCode())){
                    if (dividendModel.getDividendDate().compareTo(DateUtils.formatDate4(new Date())) < 0){
                        totalDividend = MoneyUtils.add(totalDividend,dividendModel.getDividendBalance());
                        portfolioDividend = MoneyUtils.add(dividendModel.getDividendBalance(),portfolioDividend);
                    }
                }
            }

            //累计收益
            if (mapIncome.get(combSharesQryModel.getTradeAcco()) != null){
                for (IncomeModel incomeModel : mapIncome.get(combSharesQryModel.getTradeAcco())){
                    if (incomeModel.getFundCode().equals(assetFundModel.getFundCode())){
                        assetFundModel.setTotalAccumIncome(MoneyUtils.add(incomeModel.getAccumIncome(),totalDividend));
                        break;
                    }
                }
            }

//            BigDecimal lastUnitValue = lastNetValues.get(assetFundModel.getFundCode());
//            BigDecimal margin = MoneyUtils.subtract(assetFundModel.getNetValue(), lastUnitValue);
            todayIncome = todayIncome.setScale(2, BigDecimal.ROUND_HALF_UP);
            assetFundModel.setTotalTodayIncome(todayIncome);
            BigDecimal worthValue = currentShare.multiply(assetFundModel.getNetValue());
            worthValue = worthValue.setScale(2, BigDecimal.ROUND_HALF_UP);
            //设置每个基金的资产
            assetFundModel.setTotalWorthValue(worthValue);
            portfolioFunds.add(assetFundModel);
            portfolioWorthValue = MoneyUtils.add(portfolioWorthValue, worthValue);
            portfolioTodayIncome = MoneyUtils.add(portfolioTodayIncome, todayIncome);
        }
        for (AssetFundModel assetFundModel : portfolioFunds){
            BigDecimal rate = assetFundModel.getTotalWorthValue().divide(portfolioWorthValue,4,ROUND_HALF_DOWN);
            assetFundModel.setInvestRate(rate);
        }
        portfolioModel.setNetValueDate(netValueDate);
        portfolioModel.setPortfolioCode(combSharesQryModels.get(0).getPortfolioCode());
        portfolioModel.setTradeAcco(portfolioFunds.get(0).getTradeAcco());
        //portfolioModel.setProtocolName(portfolioMap.get(portfolio).get(0).getProtocolName());
        portfolioModel.setPortfolioFunds(portfolioFunds);
        portfolioModel.setPortfolioTodayIncome(portfolioTodayIncome);
        portfolioModel.setPortfolioWorthValue(portfolioWorthValue);
        if(combIncomeQryModel != null){
            //组合累计收益 不需要另加分红
            portfolioModel.setPortfolioAccumIncome(combIncomeQryModel.getCombSumIncome());
            portfolioModel.setPortfolioShareIncome(combIncomeQryModel.getCombSumIncome());
        }
        return portfolioModel;
    }

    /**
     * 组合昨日收益计算
     */
    public static BigDecimal getPortfolioTotalIncome(PortfolioModel portfolioModel){
        BigDecimal totalTodayIncome = new BigDecimal(0);
        for (AssetFundModel assetFundModel : portfolioModel.getPortfolioFunds()){
            BigDecimal todayIncome = new BigDecimal(0);
            for (PortfolioTradeModel portfolioTradeModel : portfolioModel.getPortfolioTrades()){
                for (AssetFundModel assetFundModel1 : portfolioTradeModel.getPortfolioFunds()){
                    if (assetFundModel.getFundCode().equals(assetFundModel1.getFundCode())){
                        todayIncome = MoneyUtils.add(todayIncome,assetFundModel1.getTotalTodayIncome());
                    }
                }
            }
            totalTodayIncome = MoneyUtils.add(totalTodayIncome,todayIncome);
            assetFundModel.setTotalTodayIncome(todayIncome);
        }
        return totalTodayIncome;
    }

    /**
     * 计算每笔持仓的份额，当日收益，净值日期， 日收益    组合外基金
     *
     * @param
     * @param lookups
     * @param fundNetValueList
     * @return
     */
    public static List<AssetFundModel> extractFundsWithoutPortfolio(List<ShareDetailTotalModel> shareDetailTotalModels, List<Lookup> lookups,
                                                                    List<FundNetValueResult> fundNetValueList) {
        List<AssetFundModel> funds = new ArrayList<>();
        Map<String, FundNetValueResult> map = new HashMap<>();
        // 计算份额，当日收益，净值日期， 日收益
        for (ShareDetailTotalModel shareDetailTotalModel : shareDetailTotalModels) {
            // 如果当前份额为0，则不考虑在内
            BigDecimal currentShare = MoneyUtils.add(shareDetailTotalModel.getEnableShares(), shareDetailTotalModel.getBusinessFrozenAmount());
            if (MoneyUtils.compareTo(currentShare, 0) == 0) {
                continue;
            }

            // 从聚源获取基金基础信息
            String fundCode = shareDetailTotalModel.getFundCode();
            FundNetValueResult netValueResult = null;

            AssetFundModel assetFundModel = new AssetFundModel();
            netValueResult = setNetValue(fundCode, netValueResult, fundNetValueList);
            // 基金代码
            assetFundModel.setFundCode(shareDetailTotalModel.getFundCode());
            // 当前份额
            assetFundModel.setCurrentShares(currentShare);
            // 单位净值
            assetFundModel.setNetValue(netValueResult.getUnitNV());
            // 单位净值日期
            assetFundModel.setNetValueDate(netValueResult.getTradingDay());
            // 资产类型
            assetFundModel.setAssetType(GlobalConstant.ASSET_TYPE_FUND);
            // 累计收益
            //assetFundModel.setAccumIncome(share.getAccumIncome());
            // 累计收益 = 每月5号06文件中的“红利资金” + 每日05文件中的“货币基金未分配收益金额”
            assetFundModel.setUnpaidIncome(shareDetailTotalModel.getUnpaidIncome());
            setIncome(netValueResult, fundCode, assetFundModel, lookups);


            funds.add(assetFundModel);
        }

        return funds;
    }

    /**
     * 计算每笔持仓的份额，当日收益，净值日期， 日收益
     *
     * @param shares
     * @param lookups
     * @param fundNetValueList
     * @return
     */
    public static List<AssetFundModel> extractFunds(List<ShareModel> shares, List<Lookup> lookups,
                                                    List<FundNetValueResult> fundNetValueList) {
        List<AssetFundModel> funds = new ArrayList<>();
        Map<String, FundNetValueResult> map = new HashMap<>();
        // 计算份额，当日收益，净值日期， 日收益
        for (ShareModel share : shares) {
            // 如果当前份额为0，则不考虑在内
            BigDecimal currentShare = share.getCurrentShare();

            // 从聚源获取基金基础信息
            String fundCode = share.getFundCode();
            FundNetValueResult netValueResult = new FundNetValueResult();


            AssetFundModel assetFundModel = new AssetFundModel();
            netValueResult = setNetValue(fundCode, netValueResult, fundNetValueList);
            //交易账号
            assetFundModel.setTradeAcco(share.getTradeAccount());
            //可用份额
            assetFundModel.setEnableShares(share.getEnableShares());
            // 基金代码
            assetFundModel.setFundCode(share.getFundCode());
            // 当前份额
            assetFundModel.setCurrentShares(currentShare);
            // 单位净值
            assetFundModel.setNetValue(netValueResult.getUnitNV());
            // 单位净值日期
            assetFundModel.setNetValueDate(netValueResult.getTradingDay());
            //基金名称
            assetFundModel.setFundName(netValueResult.getChiNameAbbr());
            // 资产类型
            assetFundModel.setAssetType(GlobalConstant.ASSET_TYPE_FUND);
            // 累计收益
            assetFundModel.setAccumIncome(share.getAccumIncome());
            // 累计收益 = 每月5号06文件中的“红利资金” + 每日05文件中的“货币基金未分配收益金额”
            assetFundModel.setUnpaidIncome(share.getUnpaidIncome());
            //成本
            assetFundModel.setCost(share.getCost());
            //银行账号
            assetFundModel.setUserBankNo(share.getBankAccount());
            //银行简称
            assetFundModel.setBankCode(share.getBankCode());
            //银行名称
            assetFundModel.setBankName(share.getBankName());
            //资金类型
            assetFundModel.setCapitalMode(share.getCapitalMode());
            //分红方式
            assetFundModel.setAutoBuy(share.getAutoBuy());
            //交易账号
            assetFundModel.setTradeAcco(share.getTradeAccount());
            //前端基金类型
            assetFundModel.setAppFundType(netValueResult.getFundTypeCode());
            setIncome(netValueResult, fundCode, assetFundModel, lookups);
            //logger.warn("share未付收益：{}", share.getUnpaidIncome());
            //logger.debug("银行编号1：{}，银行名称1：{}",assetFundModel.getBankCode(),assetFundModel.getBankName());


            funds.add(assetFundModel);
        }

        return funds;
    }


    /**
     * 获取某只基金的聚源基础数据
     *
     * @param fundNetValueList
     * @param fundCode
     * @return
     */
    public static FundNetValueResult getNetValue(List<FundNetValueResult> fundNetValueList, String fundCode) {
        for (FundNetValueResult fundNetValueResult : fundNetValueList) {
            if (fundNetValueResult == null) {
                continue;
            }
            if (fundNetValueResult.getFundCode().equals(fundCode)) {
                return fundNetValueResult;
            }
        }

        return null;
    }

    /**
     * 将产品List转换成Map<code,name>
     *
     * @param products
     * @return key是基金code，value是name
     */
    public static Map<String, String> convertProductsToMap(List<SecurityProduct> products) {
        Map<String, String> codeMap = new HashMap<String, String>();
        if (CollectionUtils.isEmpty(products)) {
            return codeMap;
        }

        for (SecurityProduct product : products) {
            if (codeMap.containsKey(product.getSecuCode())) {
                continue;
            }
            // 添加到MAP
            codeMap.put(product.getSecuCode(), product.getChiName());
        }

        return codeMap;
    }

    /**
     * 累计快速赎回的份额
     *
     * @param applys
     * @return
     */
    public static Map<String, BigDecimal> getFastSellShares(List<ApplyModel> applys) {
        Map<String, BigDecimal> map = new HashMap<>();
        BigDecimal shares = new BigDecimal(0);
        for (ApplyModel model : applys) {
            String fundCode = model.getFundCode();
            if (!map.containsKey(fundCode)) {
                map.put(fundCode, new BigDecimal(0));
            }

            // 获取之前份额
            shares = map.get(fundCode);

            // 快速赎回成功 - 实时确认成功
            if (model.getTAConfirmFlag().equals(GlobalConstant.TACONFIRM_FLAG_REAL_SUCCESS)) {
                shares = MoneyUtils.add(shares, model.getShares());
            }

            // 保存
            map.put(fundCode, shares);
        }

        return map;
    }

    /**
     * 获取净值日期
     *
     * @param funds
     * @param lookups
     * @return
     */
    public static Date getNetDate(List<FundNetValueResult> funds, List<Lookup> lookups) {
        for (Lookup lookup : lookups) {
            logger.warn("getNetDate-ruleValue:" + lookup.getRuleValue());
            for (FundNetValueResult fund : funds) {
                if (fund != null) {
                    String fundCode = fund.getFundCode();
                    logger.warn("getNetDate-fundCode:" + fundCode);
                    if (fundCode != null && fundCode.equals(lookup.getRuleValue())) {
                        return fund.getTradingDay();
                    }
                }
            }
        }

        logger.warn("getNetDate-未找到T0基金或未找到T0基金的净值日期");

        return new Date();
    }

    /**
     * 如果valueOne before valueTwo，则返回true，否则返回false
     *
     * @param valueOne
     * @param valueTwo
     * @return
     */
    public static boolean dateBefore(Date valueOne, Date valueTwo) {
        valueOne = DateUtils.stringToDate(DateUtils.formatDate4(valueOne), GlobalConstant.DATE_FORMAT_YYYYMMDD);
        valueTwo = DateUtils.stringToDate(DateUtils.formatDate4(valueTwo), GlobalConstant.DATE_FORMAT_YYYYMMDD);
        if (valueOne.before(valueTwo)) {
            return true;
        }

        return false;
    }

    //获取瑞富宝收益
    public static List<IncomeModel> getIncomeWallet(List<IncomeModel> incomeModels, List<Lookup> lookups){
        List<String> fundCodes = new ArrayList<>();
        List<IncomeModel> incomeModelsWallet = new ArrayList<>();
        for (IncomeModel incomeModel : incomeModels){
            if (fundCodes.contains(incomeModel.getFundCode())){
                break;
            }else {
                fundCodes.add(incomeModel.getFundCode());
            }
            if (isT0Fund(lookups,incomeModel.getFundCode())){
                incomeModelsWallet.add(incomeModel);
            }
        }
        return incomeModelsWallet;
    }

    //获取普通基金收益
    public static List<IncomeModel> getIncomeNormal(List<IncomeModel> incomeModels, List<Lookup> lookups){
        List<String> fundCodes = new ArrayList<>();
        List<IncomeModel> incomeModelsNormal = new ArrayList<>();
        for (IncomeModel incomeModel : incomeModels){
            if (fundCodes.contains(incomeModel.getFundCode())){
                break;
            }else {
                fundCodes.add(incomeModel.getFundCode());
            }
            if (!isT0Fund(lookups,incomeModel.getFundCode())){
                incomeModelsNormal.add(incomeModel);
            }
        }
        return incomeModelsNormal;
    }
}
